package com.miracle.test;

import com.miracle.entity.Male;
import com.miracle.entity.Person;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public class Stream使用 {
    public static void main(String[] args) {
        Person p1 = new Person("小一", "男", 12,"20230503",  165, 50.1, new BigDecimal("3000"),"01", "", "", true);
        Person p2 = new Person("小二", "男", 5,"20231205",  165, 50.1, new BigDecimal("5100"),"01", "", "", true);
        Person p3 = new Person("小三", "女", 24,"20230106",  165, 50.1, new BigDecimal("3200"),"05", "", "", true);
        Person p4 = new Person("小四", "男", 60,"20230308",  165, 50.1, new BigDecimal("2500"),"05", "", "", true);
        Person p5 = new Person("小五", "女", 24,"20230805",  165, 50.1, new BigDecimal("9700"),"05", "", "", true);
        Person p6 = new Person("小六", "男", 36,"20231110",  165, 50.1, new BigDecimal("8700"),"01", "", "", true);
        Person p7 = new Person("小七", "女", 45,"20230206",  165, 50.1, new BigDecimal("6600"),"03", "", "", true);
        Person p8 = new Person("小八", "男", 3,"20230519",  165, 50.1, new BigDecimal("5400"),"03", "", "", true);
        Person p9 = new Person("小九", "女", 87,"20230922",  165, 50.1, new BigDecimal("1200"),"03", "", "", true);
        ArrayList<Person> peoples = new ArrayList<Person>(){{
            add(p1);
            add(p2);
            add(p3);
            add(p4);
            add(p5);
            add(p6);
            add(p7);
            add(p8);
            add(p9);
        }};

        //选按照日期排序，然后按照addr分组
        LinkedHashMap<String, List<Person>> collect1 = peoples.stream().sorted(Comparator.comparing(Person::getBirth, Comparator.nullsLast(Comparator.naturalOrder())))
                .collect(Collectors.groupingBy(Person::getAddr, LinkedHashMap::new, Collectors.toList()));

        //先按照addr排序，然后按照addr分组，然后组内按照birth排序
        LinkedHashMap<String, List<Person>> collect2 = peoples.stream().sorted(Comparator.comparing(Person::getAddr, Comparator.nullsLast(Comparator.naturalOrder())))
                .collect(Collectors.groupingBy(Person::getAddr,
                        LinkedHashMap::new,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list ->
                                        list.stream().sorted(Comparator.comparing(Person::getBirth, Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList())
                        )
                )
                );

        //先按照addr排序，然后按照addr分组，然后组内按照birth排序；然后对组内list求和放到新的Person对象
        LinkedHashMap<String, Person> collect3 = peoples.stream().sorted(Comparator.comparing(Person::getAddr, Comparator.nullsLast(Comparator.naturalOrder())))
                .collect(Collectors.groupingBy(Person::getAddr,
                                LinkedHashMap::new,
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        list ->
                                                list.stream().sorted(Comparator.comparing(Person::getBirth, Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList())
                                )
                        )
                )
                .entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e->{
                    BigDecimal sum = e.getValue().stream().map(Person::getSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
                    Person person = new Person();
                    person.setSalary(sum);
                    return person;
                },(a, b) -> b,LinkedHashMap::new) );

        // 先根据addr分组，在根据sex分组，然后对每个sex组内Salary求和，结果生成一个新Person，最终得到结构为LinkedHashMap<String, LinkedHashMap<String, Person>>的数据
        LinkedHashMap<String, LinkedHashMap<String, Person>> collect4 = peoples.stream()
                .collect(
                    Collectors.groupingBy(
                        Person::getAddr,
                        LinkedHashMap::new,
                        Collectors.groupingBy(
                            Person::getSex,
                            LinkedHashMap::new,
                            Collectors.toList()
                        )
                    )
                )
                .entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey,
                        entry -> entry.getValue().entrySet().stream()
                                .map(p -> {
                                    BigDecimal sum = p.getValue().stream().map(Person::getSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
                                    Person person = new Person();
                                    person.setSalary(sum);
                                    person.setSex(p.getKey());
                                    return person;
                                })
                                .collect(Collectors.toMap(Person::getSex, p->p, (a, b) -> b, LinkedHashMap::new)),
                        (a, b) -> b,
                        LinkedHashMap::new)
                );





        System.out.println(collect4);

        System.out.println(collect1);
        System.out.println(collect2);


    }
}
